# 数据容器

# 不限制类型，可以嵌套数组
my_list = ["a",1,True]
my_list2 = list()
my_list3 = [["1"],["2","3"],["3","4","5"]]

print(my_list[0])

#倒叙取出
print(my_list[-1]) #倒数第一个 True
print(my_list[-2]) #倒数第二个 1
print(my_list[-3]) #倒数第三个 "a"

num = 1
def setNum(n):
    # global num  #方法里面调用全局属性需要使用global
    num = 2
    print(num)

print(num)
setNum(num)
print(num)

class MyClass:
    def hello(self,name):
        return name

print(MyClass().hello("张三"))

#方法
# index 查找索引
my_list = ["1","2","3"]
index = my_list.index("3") #存在返回索引，不存在报错
print(index)
# my_list.index("4") #不存在报错

# 赋值
my_list = ["1","2","3"]
my_list[1] = "4"
print(my_list) # ['1', '4', '3']

#插入
my_list = ["1","3","4"]
my_list.insert(1,"2")
print(my_list) #['1', '2', '3', '4']

# 添加到尾部
my_list = ["1","3","4"]
my_list.append("5")
print(my_list) #['1', '3', '4', '5']

# 添加多个元素到尾部
my_list1 = ["1","2","3"]
my_list2 = ["4","4","4"]
my_list1.extend(my_list2)
print(my_list1) #['1', '2', '3', '4', '4', '4']

#删除指定下标元素 del list[index]
my_list = ["1","2","3"]
del my_list[1]
print(my_list) # ['1', '3']

#删除指定下标元素并返回 my_list.pop(index)
my_list = ["1","2","3"]
pop1 = my_list.pop(1)
print(pop1) # ['1', '3']
print(my_list) # ['1', '3']
pop2 = my_list.pop(-1) #删除最后的元素 3
print(pop2) #3
print(my_list) #['1']

#删除第一个匹配的元素
my_list = ["1","2","3","2"]
print(my_list.remove("2")) #None
print(my_list) #['1', '3']

#清空元素
my_list = ["1","2","3","2"]
my_list.clear()
print(my_list) #[]

#统计元素出现数量
my_list = ["1","2","2","2"]
count = my_list.count("2")
print(count) #3

#统计数组总数量
my_list = ["1","2","2","2"]
count = len(my_list)
print(count) #4


#练习案例:常用功能练习
# 有一个列表，内容是:[21,25,21,23,22,20]，记录的是一批学生的年龄
# 请通过列表的功能（方法），对其进行
# 1．定义这个列表，并用变量接收它2．追加一个数字31，到列表的尾部
# 3．追加一个新列表[29，33,30]，到列表的尾部4．取出第一个元素（应是:21)
# 5．取出最后一个元素（应是:30)
# 6．查找元素31，在列表中的下标位置

my_list = [21,25,21,23,22,20]
my_list.append(31)
my_list.extend([29,33,30])
# my_list.pop(0)
# my_list.pop(-1)
list_0 = my_list[0]
print("第一个{%d}"%list_0)
list_last = my_list[-1] #第一个{21}
print("最后一个{%d}"%list_last)
print(my_list.index(31)) #最后一个{30}
print(my_list)

#元组
#定义元组字面量
("元素1","元素2","元素3")
# 定义元组变量
tp1 = ("元素1","元素2","元素3")
#定义空元组
tp2 = ()  #方式1
tp3 = tuple() #方式2

# 定义单个元组，后面需要有括号
tp4 = ("元素1",)

#取元组的元素内容
tp1 = ("元素1","元素2","元素3")
print(tp1[1]) #元素2

#元组-查找
tp1 = ("元素1","元素2","元素3")
print(tp1.index("元素2")) # 1
#元组-长度
tp1 = ("元素1","元素2","元素3")
print(len(tp1)) #3
#元组-出现次数
tp1 = ("元素1","元素2","元素3","元素1")
print(tp1.count("元素1")) # 2


#字符串
str1 = "字符串"

#index使用
str1 = "字符串"
print(str1.index("字")) # 0

#replace使用
str1 = "字符串"
str2 = str1.replace("字", "111")
print(str1) #字符串
print(str2) #111符串

#split使用
str1 = "字 符 串"
str2 = str1.split(" ")
print(str2) #['字', '符', '串']

#strip取出前后缀 （默认空格和回车）
str1 = "   字符串   "
str2 = str1.strip()
print(str2)
#strip传参
str1 = "123字符串312"
str2 = str1.strip("12") #去掉首尾的1,2
print(str2)

#次数count
str1 = "字符串字"
print(str1.count("字"))

#长度len
str1 = "字符串"
print(len(str1))



#序列反转 挡步长为负数时，begin和end也要反转
my_list = ["1","2","3","4"]
my_list = my_list[3:0:-1]
print(my_list) #['4', '3', '2']

my_list = ["1","2","3","4","5"]
my_list = my_list[3:1:-1]
print(my_list) #4 3

#获取黑马程序员
# 1.
str1 = "万过薪月,员序程马黑来,nohtyP学"
#倒序字符串，切片取出或切片取出，然后倒序
print(str1[9:4:-1])
#split分隔", " replace替换"来"为空，倒序字符串
split = str1.split(",")
replace = split[1].replace("来", "")
print(replace[::-1])


#Set集合创建
my_set = {"1","2","3"}
print(my_set)
my_set = set()

#add添加
my_set.add("test1")
my_set.add("test2")
print(my_set)

#remove删除
my_set = {"1","2","3"}
my_set.remove("1")
print(my_set) # {'2', '3'}

#pop随机删除个元素,没有参数
my_set = {"1","2","3"}
my_set.pop()
print(my_set)

#clear清空
my_set = {"1","2","3"}
my_set.clear()
print(my_set) #set()

#取差集 set1.difference(set2) 取出set1中不在set2中的元素，注意不会修改set1
my_set1 = {"1","2","3"}
my_set2 = {"2","3","4"}
my_set3 = my_set1.difference(my_set2)
print(my_set1) #{'2', '3', '1'}
print(my_set2) #{'4', '2', '3'}
print(my_set3)#{'1'}

#消除差集 set1.difference_update(set2) 只保留set1中不存在set2的元素，注意会修改set1
my_set1 = {"1","2","3"}
my_set2 = {"2","3","4"}
my_set1.difference_update(my_set2) #
print(my_set1) ##{'1'}

#合并 set1.union(set2) 注意会去重
my_set1 = {"1","2","3"}
my_set2 = {"2","3","4"}
my_set3 = my_set1.union(my_set2)
print(my_set1) #{'2', '3', '1'}
print(my_set2) #{'4', '2', '3'}
print(my_set3) #{'4', '2', '3', '1'}

#统计数量 len
my_set1 = {"1","2","3"}
print(len(my_set1))

#遍历集合
my_set1 = {"1","2","3"}
for i in my_set1:
    print(i)

#字典dict
#定义
my_dict = {"key1":"value1","key2":"value2"}
#定义空字典
my_dict = {}  #方式1
my_dict = dict() #方式2

#通过key获取value
my_dict = {"key1":"value1","key2":"value2"}
print(my_dict["key1"])

#可以嵌套，但是key不能是字典
my_dict = {"key1":"value1","key2":{"key3":"value3"}}
print(my_dict["key2"]["key3"])
my_dict = {"key1":"value1","key2":{"key3":{"key4":"value4"}}}
print(my_dict["key2"]["key3"]["key4"])

#字典新增元素 dict[key] = value
my_dict = {"key1":"value1","key2":"value2"}
my_dict["key3"] = "value3"
print(my_dict)

#字典修改元素 dict[key] = value
my_dict = {"key1":"value1","key2":"value2"}
my_dict["key1"] = "value3"
print(my_dict)

#删除并返回元素 dict.pop(key)
my_dict = {"key1":"value1","key2":"value2"}
pop = my_dict.pop("key1")
print(my_dict)
print("被删除的元素%s",pop)

#清空元素clear()
my_dict = {"key1":"value1","key2":"value2"}
my_dict.clear()
print(my_dict)

# 获取全部key dict.keys()
my_dict = {"key1":"value1","key2":"value2"}
for i in my_dict.keys():
    print(i)

#遍历字典的value
#方式1 使用for,也可以直接获取所有key
my_dict = {"key1":"value1","key2":"value2"}
for i in my_dict:
    print(i)
    print(my_dict[i])
#方式2 使用keys
my_dict = {"key1":"value1","key2":"value2"}
for i in my_dict.keys():
    print(i)
    print(my_dict[i])

#统计字典元素数量
my_dict = {"key1":"value1","key2":"value2"}
print(len(my_dict))

#len()获取多种数据容器的长度
my_list = ["1","2","3"]
print(len(my_list))
my_tuple = ("1","2","3")
print(len(my_tuple))
my_dict = {"key1":"value1","key2":"value2"}
print(len(my_dict))

#max()获取最大值
my_list = [1,2,3,4,5]
print(max(my_list)) #5
my_tuple = (1,2,3,4,5)
print(max(my_tuple)) #5

#min() 获取最小值
my_list = [1,2,3,4,5]
print(min(my_list)) #1
my_tuple = (1,2,3,4,5)
print(min(my_tuple)) #1

#数据容器类型转换
#定义每种数据类型 各一种
my_list = [1,2,3,4,5]
my_tuple = (1,2,3,4,5)
my_str = "12345"
my_set = {1,2,3,4,5}
my_dict = dict(key1="value1",key2="value2")

#类型转换:容器转列表list
print(f"列表转列表{list(my_list)}")
print(f"元组转列表{list(my_tuple)}")
print(f"字符串转列表{list(my_str)}")
print(f"集合转列表{list(my_set)}")
print(f"字典转列表{list(my_dict)}")

#类型转换:容器转元组tuple
print(f"列表转元组{tuple(my_list)}")
print(f"元组转元组{tuple(my_tuple)}")
print(f"字符串转元组{tuple(my_str)}")
print(f"集合转元组{tuple(my_set)}")
print(f"字典转元组{tuple(my_dict)}")

#类型转换:容器转字符串
my_list = ['1','2','3','4','5']
print(f"列表转字符串{str(my_list)}")
print(f"元组转字符串{str(my_tuple)}")
print(f"字符串转字符串{str(my_str)}")
print(f"集合转字符串{str(my_set)}")
print(f"字典转字符串{str(my_dict)}")

#类型转换:容器转集合set
print(f"列表转集合{set(my_list)}")
print(f"元组转集合{set(my_tuple)}")
print(f"字符串转集合{set(my_str)}")
print(f"集合转集合{set(my_set)}")
print(f"字典转集合{set(my_dict)}")

#类型转换:容器转字典dict 错误，不允许
# print(f"列表转字典{dict(my_list)}")

#排序 sorted(list,reverse = True) 注意不会修改原数据容器的顺序, 返回排序后的新列表
my_list = [1,3,4,2,5]
# my_list.sort()
l = sorted(my_list)
print(my_list) #[1, 3, 4, 2, 5]
print(l) #[1, 2, 3, 4, 5]
#反序
my_list = [1,3,4,2,5]
l = sorted(my_list,reverse=True)
l = sorted(my_list,reverse=True)
print(my_list) #[1, 3, 4, 2, 5]
print(l) #[5, 4, 3, 2, 1]

def test_re():
    return 1,2

#多个接收
x,y = test_re()
print(x) #1
print(y) #2

#单个接收为元组
z = test_re()
print(z) #(1, 2)
print(type(z)) #<class 'tuple'>


# 函数参数种类
def test_args(a,b,c):
    print(a)
    print(b)
    print(c)
#1.位置传参
test_args(1,2,3)

#2.关键字传参
test_args(b=1,a=2,c=3)

#混合使用,位置参数需要在前面(优先匹配)，关键字参数需要在后面，但关键字参数可以不在顺序上
test_args(1,b=2,c=3)
#在Python中，关键字参数和位置参数混合使用时遵循以下规则：
# 位置参数必须出现在关键字参数之前。
# Python会首先根据位置匹配位置参数。
# 然后根据名称匹配关键字参数。
# 具体来说：
# 位置参数优先：Python会先将按顺序传递的值分配给函数定义中的参数，直到所有位置参数都被赋值。
# 关键字参数随后匹配：剩余的参数通过关键字进行匹配。这意味着你可以为任意位置的参数指定值，只要使用了正确的参数名。
def test_args(a, b, c):
    print(f"a={a}, b={b}, c={c}")

# 位置参数在前，关键字参数在后
test_args(1, b=2, c=3)  # 输出: a=1, b=2, c=3

# 全部使用关键字参数
test_args(c=3, b=2, a=1)  # 输出: a=1, b=2, c=3

# 错误示例：重复赋值a
# test_args(1, a=3, 1)  # SyntaxError: positional argument follows keyword argument

# 错误示例：位置参数不能出现在关键字参数之后
# test_args(b=2, c=3, 1)  # 这将引发SyntaxError

#缺省参数(默认参数)
def test_args(a,b,c=3):
    print(a)
    print(b)
    print(c)
test_args(1,2) # 1 2 3
#注意：设置默认值必须在最后
# def test_args(a=1,b,c): #SyntaxError: non-default argument follows default argument
#     print(a)
#     print(b)
#     print(c)

# 不定长参数*args，默认为元组。重点是*,后面的args可以自定义
def test_args(*args):
    print(args)
    print(type(args))#<class 'tuple'>
    for i in args:
        print(i)#1 2 3 4 5
test_args(1,2,3,4,5)

#关键字传递**kwargs，需要传入key-value格式，接收默认为字典。重点是**,后面的kwargs可以自定义
def test_args(**kwargs):
    print(kwargs)
    print(type(kwargs))#<class 'dict'>
    for i in kwargs:
        print(i,kwargs[i])#a 1 b 2 c 3
test_args(a=1,b=2,c=3)

#匿名函数，函数作为参数传递
def test_args(func):
    print(func(x,y)) #3
def test_func(x,y):
    print("test_func")
    return x + y
test_args(test_func)#直接把函数名传入

#lambda匿名函数
def test_args(func):
    print(func(x,y)) #3
test_args(lambda x,y:x+y)
